package com.xiaoka.ins.corp.api.gpic.service;

import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.entity.StringEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.xiaoka.freework.utils.Utils;
import com.xiaoka.freework.utils.http.HttpExecutor;
import com.xiaoka.ins.corp.api.config.GpicConfig;
import com.xiaoka.ins.corp.api.dto.request.PremiumCalculationParam;
import com.xiaoka.ins.corp.api.dto.request.RiskDto;
import com.xiaoka.ins.corp.api.dto.request.UnderwritingDto;
import com.xiaoka.ins.corp.api.gpic.dto.ApplicantInfo;
import com.xiaoka.ins.corp.api.gpic.dto.HeaderElementGPIC;
import com.xiaoka.ins.corp.api.gpic.dto.RequestElementGPIC;
import com.xiaoka.ins.corp.api.gpic.dto.RequestElementGPIC.InputsElement_gpic;
import com.xiaoka.ins.corp.api.gpic.dto.RequestElementGPIC.InputsElement_gpic.InputElement_gpic;
import com.xiaoka.ins.corp.api.gpic.dto.RequestElementGPIC.OrderElement;
import com.xiaoka.ins.corp.api.gpic.dto.RequestElementGPIC.OrderElement.SubOrderList;
import com.xiaoka.ins.corp.api.gpic.dto.RequestElementGPIC.OrderElement.SubOrderList.SubOrder;
import com.xiaoka.ins.corp.api.gpic.dto.ResponseElementGPIC.TagsList.Tags;
import com.xiaoka.ins.corp.api.gpic.dto.ResponseElementGPIC.TagsList.Tags.Tag;
import com.xiaoka.ins.corp.api.gpic.dto.ResponseElementGPIC.TagsList.Tags.Tag.Definition;
import com.xiaoka.ins.corp.api.gpic.dto.RootElementGPIC;
import com.xiaoka.ins.corp.api.gpic.dto.RootElementGPIC.Package;
import com.xiaoka.ins.corp.api.gpic.dto.VcodeEnum;
import com.xiaoka.ins.corp.api.gpic.dto.VehicleInfo;
import com.xiaoka.ins.corp.api.gpic.dto.config.Regions;
import com.xiaoka.ins.corp.api.gpic.help.DataConversion;
import com.xiaoka.ins.corp.api.gpic.help.GpicUtils;
import com.xiaoka.ins.corp.api.gpic.service.impl.GpicServiceImpl;
import com.xiaoka.ins.corp.api.utils.BaseUtils;
import com.xiaoka.ins.corp.api.utils.JaxbUtils;

/**
 * 国寿财车险接口 
 * 
 * @author zheng
 *
 */
@Component
public class GpicInterface {
	
	@Autowired
	private GpicConfig gpicConfig;
	
	@Autowired
	private JaxbUtils jaxbUtils;
	
	private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
	
	/**
	 * 获取报价接口
	 * @param pc
	 * @return
	 */
	public RootElementGPIC doRequest100(PremiumCalculationParam pc){
		RootElementGPIC root = new RootElementGPIC();
		Package _package = new Package();
		HeaderElementGPIC header = new HeaderElementGPIC(100,pc.getId());
		header.setSellerId(gpicConfig.getSellerId());
		RequestElementGPIC request = new RequestElementGPIC();
		
		List<InputsElement_gpic> inputsList = new ArrayList<InputsElement_gpic>();
		List<InputElement_gpic> inputList = new ArrayList<InputElement_gpic>();
		InputsElement_gpic inputs = new InputsElement_gpic();
		
		inputList.add(new InputElement_gpic(VehicleInfo.licenseNo.name(),pc.getCustomerDto().getVehicleLicenceCode()));//车牌号  新车为空
		inputList.add(new InputElement_gpic(VehicleInfo.cityCode.name(),Regions.getCityCode(pc.getCustomerDto().getCityId())));//城市代码
		inputList.add(new InputElement_gpic(VehicleInfo.noLicenseFlag.name(),"0"));//新车未上牌  1：新车，0：非新车
		inputList.add(new InputElement_gpic(VehicleInfo.idNo.name(),BaseUtils.getBirthdayByID(pc.getCustomerDto().getIdNo())));  //身份证后四位
		inputList.add(new InputElement_gpic(VehicleInfo.idNoType.name(),pc.getCustomerDto().getIdType()));//证件类型
		
		inputs.setType("vehicleInfo");
		
		inputs.setInputs(inputList);
		inputsList.add(inputs);
		request.setInputsList(inputsList);
		_package.setRequest(request);
		_package.setHeader(header);
		root.set_package(_package);
		return sendRequest(root);
	}

	/**
	 * 补充报价信息接口
	 * @param response100
	 * @param pc
	 * @return
	 */
	public RootElementGPIC doRequest105(RootElementGPIC response100,PremiumCalculationParam pc){
		RootElementGPIC root = new RootElementGPIC();
		Package _package = new Package();
		HeaderElementGPIC header = new HeaderElementGPIC(105,response100.get_package().getHeader().getSessionId());
		RequestElementGPIC request = new RequestElementGPIC();
		List<InputsElement_gpic> inputsList = new ArrayList<InputsElement_gpic>();
		InputsElement_gpic inputs1 = new InputsElement_gpic();
		InputsElement_gpic inputs2 = new InputsElement_gpic();
		List<InputElement_gpic> inputList1 = new ArrayList<InputElement_gpic>();
		List<InputElement_gpic> inputList2 = new ArrayList<InputElement_gpic>();
		
		Map<String,String> paramMap = DataConversion.get105RequestMap(pc);
		for(Tags tags:response100.get_package().getResponse().getTagsList().getTags()){
			for(Tag tag:tags.getTag()){
				for(Definition def:tag.getDefinition()){
					if("key".equals(def.getName())){
						if("vehicleInfo".equals(tags.getType())){
							inputList1.add(new InputElement_gpic(def.getValue(),paramMap.get(def.getValue())));
						}else if("ownerInfo".equals(tags.getType())){
							inputList2.add(new InputElement_gpic(def.getValue(),paramMap.get(def.getValue())));
						}
					}
				}
			}
		}
		inputs1.setInputs(inputList1);
		inputs1.setType("vehicleInfo");
		inputsList.add(inputs1);
		if(inputList2.size()>0){
			inputs2.setInputs(inputList2);
			inputs2.setType("ownerInfo");
			inputsList.add(inputs2);
		}
		request.setInputsList(inputsList);
		_package.setRequest(request);
		_package.setHeader(header);
		root.set_package(_package);
		return sendRequest(root);
	}

	/**
	 * 报价接口
	 * @param pc
	 * @param sessionId
	 * @return
	 */
	public String doRequest110(PremiumCalculationParam pc,String sessionId) {
		RootElementGPIC root = new RootElementGPIC();
		Package _package = new Package();
		HeaderElementGPIC header = new HeaderElementGPIC(110,sessionId);
		RequestElementGPIC requestElement = new RequestElementGPIC();
		List<InputsElement_gpic> inputsList = new ArrayList<InputsElement_gpic>();
		
		InputsElement_gpic inputs1 = new InputsElement_gpic();
		List<InputElement_gpic> inputList1 = new ArrayList<InputElement_gpic>();
		for(RiskDto r:pc.getRiskDtoList()){
			if(VcodeEnum.bizFlag.name().equals(r.getCode())){//商业险必保
				inputList1.add(new InputElement_gpic(VcodeEnum.bizFlag.name(),"1"));
			}else if(StringUtils.isNotBlank(r.getCode())){
				String value = StringUtils.isBlank(r.getValue().toString())?"1":r.getValue().toString();
				inputList1.add(new InputElement_gpic(r.getvCode(),value));
			}
		}
		inputs1.setInputs(inputList1);
		inputs1.setType("optional");
		
		InputsElement_gpic inputs2 = new InputsElement_gpic();
		List<InputElement_gpic> inputList2 = new ArrayList<InputElement_gpic>();
		inputList2.add(new InputElement_gpic(VehicleInfo.bizBeginDate.name(),dateFormat.format(pc.getCustomerDto().getBegin())));
		inputList2.add(new InputElement_gpic(VehicleInfo.forceBeginDate.name(),dateFormat.format(pc.getCustomerDto().getBegin())));
		inputs2.setInputs(inputList2);
		inputs2.setType("deadline");
		inputsList.add(inputs1);
		inputsList.add(inputs2);
		requestElement.setInputsList(inputsList);
		_package.setRequest(requestElement);
		_package.setHeader(header);
		root.set_package(_package);
		return  sendRequestEnd(root);
	}
	
	/**
	 * 支付检查接口
	 * 检查是否核保成功，是否可以支付，可以就返回支付地址
	 * @param seqNo
	 * @return
	 */
	public RootElementGPIC doRequest120(String seqNo) {
		/*PayOrder payOrder = payOrderRepository.findBySeqNo(seqNo);
		if(payOrder!=null){
			List<Policy> policyList = policyRepository.findByOrder(payOrder);
			OrderElement order = new OrderElement();
			String totalPremium = CommonUtils.removeDecimalPoint(payOrder.getAmount().toString());
			order.setPremium(totalPremium);
			order.setTBOrderId(seqNo);
			SubOrderList subOrderList = new SubOrderList();//biz：商业险
			ArrayList<SubOrder> list = new ArrayList<SubOrder>();
			for(Policy policy:policyList){
				String type = "biz".equals(policy.getPlancode())?"biz":"force";
				String premium = CommonUtils.removeDecimalPoint(policy.getAmount().toString());
				SubOrder subOrder = new SubOrder(type,policy.getSerialNumber(),itemId,premium);
				subOrder.setProposalNo(policy.getPolicyAppno());
				list.add(subOrder);
			}
			subOrderList.setSubOrder(list);
			order.setSubOrderList(subOrderList);
			RootElementGPIC root = new RootElementGPIC();
			Package _package = new Package();
			HeaderElementGPIC header = new HeaderElementGPIC(120,seqNo);
			RequestElementGPIC request = new RequestElementGPIC();
			request.setOrder(order);
			_package.setRequest(request);
			_package.setHeader(header);
			root.set_package(_package);
			return sendRequest(root);
		}*/
		return null;
	}
	
	/**
	 * 核保接口
	 * @param check
	 * @param pc
	 * @return
	 */
	public String doRequest115(UnderwritingDto check,PremiumCalculationParam pc){
		List<InputsElement_gpic> inputsList = new ArrayList<InputsElement_gpic>();
		InputsElement_gpic inputs1 = new InputsElement_gpic();
		String gender = BaseUtils.getGenderByID(pc.getCustomerDto().getIdNo());
		String birthday = BaseUtils.getFormatBirthday(pc.getCustomerDto().getIdNo());
		List<InputElement_gpic> inputList1 = new ArrayList<InputElement_gpic>();
		inputList1.add(new InputElement_gpic(ApplicantInfo.insuredIdNo.name(),pc.getCustomerDto().getIdNo()));//被保险人证件号码
		inputList1.add(new InputElement_gpic(ApplicantInfo.insuredName.name(),pc.getCustomerDto().getName()));//被保险人姓名
		inputList1.add(new InputElement_gpic(ApplicantInfo.insuredIdType.name(),"01"));//被保险人证件类型
		inputList1.add(new InputElement_gpic(ApplicantInfo.insuredBirthday.name(),birthday));//被保险人生日
		inputList1.add(new InputElement_gpic(ApplicantInfo.insuredMobile.name(),pc.getCustomerDto().getMobile()));//被保险人手机:
		inputList1.add(new InputElement_gpic(ApplicantInfo.insuredGender.name(),gender));//被保险人性别：证件类型非身份证时需要
		inputs1.setType("insuredInfo");//被保险人信息
		inputs1.setInputs(inputList1);
		
		InputsElement_gpic inputs2 = new InputsElement_gpic();
		List<InputElement_gpic> inputList2 = new ArrayList<InputElement_gpic>();
		
		InputsElement_gpic inputs3 = new InputsElement_gpic();
		List<InputElement_gpic> inputList3 = new ArrayList<InputElement_gpic>();
		String standardPremium = "0";
		String bizTotalPremium = "0";
		String forceTotalPremium = "0";
		Boolean forceFlag = false;
		for(RiskDto r:pc.getRiskDtoList()){
			if("forceFlag".equals(r.getCode())){
				forceFlag="1".equals(r.getValue());
				forceTotalPremium = r.getPremium().toString().replace(".", "");
				inputList2.add(new InputElement_gpic(r.getvCode(),r.getValue().toString()));
			}else if("forceTotalPremium".equals(r.getCode())||"vehicleTaxPremium".equals(r.getCode())||"forcePremium".equals(r.getCode())){
				inputList3.add(new InputElement_gpic(r.getvCode(),r.getPremium().toString().replace(".", "")));
			}else if(r.getCode().endsWith("Premium")){
				standardPremium = "standardPremium".equals(r.getCode())?r.getPremium().toString().replace(".", ""):standardPremium;
				bizTotalPremium = "bizTotalPremium".equals(r.getCode())?r.getPremium().toString().replace(".", ""):bizTotalPremium;
				inputList2.add(new InputElement_gpic(r.getvCode(),r.getPremium().toString().replace(".", "")));
			}else if(StringUtils.isNotBlank(r.getvCode())){
				inputList2.add(new InputElement_gpic(r.getvCode(),r.getValue().toString()));
			}
		}
		inputs2.setType("optional");//自由组合套餐
		inputs2.setInputs(inputList2);
		inputs3.setType("force");//交强险
		inputs3.setInputs(inputList3);
		
		InputsElement_gpic inputs4 = new InputsElement_gpic();
		List<InputElement_gpic> inputList4 = new ArrayList<InputElement_gpic>();
		inputList4.add(new InputElement_gpic(ApplicantInfo.addresseeName.name(),check.getReceiveName()));
		inputList4.add(new InputElement_gpic(ApplicantInfo.addresseeProvince.name(),""));
		inputList4.add(new InputElement_gpic(ApplicantInfo.addresseeCityName.name(),""));
		inputList4.add(new InputElement_gpic(ApplicantInfo.addresseeMobile.name(),check.getReceiveMobile()));
		inputList4.add(new InputElement_gpic(ApplicantInfo.addresseeTown.name(),""));
		inputList4.add(new InputElement_gpic(ApplicantInfo.addresseeDetails.name(),check.getReceiveAddress()));
		inputList4.add(new InputElement_gpic(ApplicantInfo.addresseeCity.name(),Regions.getCityCode(pc.getCustomerDto().getCityId())));
		inputs4.setType("deliverInfo");//配送信息
		inputs4.setInputs(inputList4);
		
		InputsElement_gpic inputs5 = new InputsElement_gpic();
		List<InputElement_gpic> inputList5 = new ArrayList<InputElement_gpic>();
		inputList5.add(new InputElement_gpic(ApplicantInfo.applicantIdType.name(),"01"));
		inputList5.add(new InputElement_gpic(ApplicantInfo.applicantMobile.name(),pc.getCustomerDto().getMobile()));
		inputList5.add(new InputElement_gpic(ApplicantInfo.applicantBirthday.name(),birthday));
		inputList5.add(new InputElement_gpic(ApplicantInfo.applicantIdNo.name(),pc.getCustomerDto().getIdNo()));
		inputList5.add(new InputElement_gpic(ApplicantInfo.applicantGender.name(),gender));
		inputList5.add(new InputElement_gpic(ApplicantInfo.applicantName.name(),pc.getCustomerDto().getName()));
		inputs5.setType("applicantInfo");//投保人信息
		inputs5.setInputs(inputList5);
		
		InputsElement_gpic inputs6 = new InputsElement_gpic();
		List<InputElement_gpic> inputList6 = new ArrayList<InputElement_gpic>();
		inputList6.add(new InputElement_gpic(ApplicantInfo.ownerIdType.name(),"01"));
		inputList6.add(new InputElement_gpic(ApplicantInfo.ownerMobile.name(),pc.getCustomerDto().getMobile()));
		inputList6.add(new InputElement_gpic(ApplicantInfo.ownerGender.name(),gender));
		inputList6.add(new InputElement_gpic(ApplicantInfo.ownerIdNo.name(),pc.getCustomerDto().getIdNo()));
		inputList6.add(new InputElement_gpic(ApplicantInfo.ownerName.name(),pc.getCustomerDto().getName()));
		inputList6.add(new InputElement_gpic(ApplicantInfo.ownerBirthday.name(),birthday));
		inputs6.setType("ownerInfo");//车主信息
		inputs6.setInputs(inputList6);
		
		InputsElement_gpic inputs7 = new InputsElement_gpic();
		List<InputElement_gpic> inputList7 = new ArrayList<InputElement_gpic>();
		inputList7.add(new InputElement_gpic("forceBeginDate",dateFormat.format(pc.getCustomerDto().getBegin())));
		inputList7.add(new InputElement_gpic("bizBeginDate",dateFormat.format(pc.getCustomerDto().getBegin())));
		inputs7.setType("deadline");//到期时间
		inputs7.setInputs(inputList7);
		
		OrderElement order = new OrderElement();
		order.setPremium(standardPremium);
		order.setTBOrderId(check.getQuerySequenceNo());
		SubOrderList subOrderList = new SubOrderList();//biz：商业险
		ArrayList<SubOrder> list = new ArrayList<SubOrder>();
		list.add(new SubOrder("biz",BaseUtils.getUniqueId(),gpicConfig.getItemId(),bizTotalPremium));
		if(forceFlag){
			list.add(new SubOrder("force",BaseUtils.getUniqueId(),gpicConfig.getItemId(),forceTotalPremium));
		}
		subOrderList.setSubOrder(list);
		order.setSubOrderList(subOrderList);
		inputsList.add(inputs1);
		inputsList.add(inputs2);
		inputsList.add(inputs3);
		inputsList.add(inputs4);
		inputsList.add(inputs5);
		inputsList.add(inputs6);
		inputsList.add(inputs7);
		
		RootElementGPIC root = new RootElementGPIC();
		Package _package = new Package();
		HeaderElementGPIC header = new HeaderElementGPIC(115,check.getQuerySequenceNo());
		RequestElementGPIC request = new RequestElementGPIC();
		request.setInputsList(inputsList);
		request.setOrder(order);
		_package.setRequest(request);
		_package.setHeader(header);
		root.set_package(_package);
		return sendRequestEnd(root);
	}
	
	/**
	 * 承保接口！
	 * 所有支付都是跳转支付！ web端只能用银联支付，app端只能用快钱支付！
	 * 如果用银联支付 ，需要请求130承保接口！
	 * @param seqNo
	 * @return
	 */
	public RootElementGPIC doRequest130(String seqNo) {
		/*PayOrder payOrder = payOrderRepository.findBySeqNo(seqNo);
		if(payOrder!=null){
			List<Policy> policyList = policyRepository.findByOrder(payOrder);
			OrderElement order = new OrderElement();
			String totalPremium = CommonUtils.removeDecimalPoint(payOrder.getAmount().toString());
			order.setPremium(totalPremium);
			order.setTBOrderId(seqNo);
			SubOrderList subOrderList = new SubOrderList();//biz：商业险
			ArrayList<SubOrder> list = new ArrayList<SubOrder>();
			for(Policy policy:policyList){
				String type = "biz".equals(policy.getPlancode())?"biz":"force";
				String premium = CommonUtils.removeDecimalPoint(policy.getAmount().toString());
				SubOrder subOrder = new SubOrder(type,policy.getSerialNumber(),itemId,premium);
				subOrder.setProposalNo(policy.getPolicyAppno());
				list.add(subOrder);
			}
			subOrderList.setSubOrder(list);
			order.setSubOrderList(subOrderList);
			RootElementGPIC root = new RootElementGPIC();
			Package _package = new Package();
			HeaderElementGPIC header = new HeaderElementGPIC(130,seqNo);
			RequestElementGPIC request = new RequestElementGPIC();
			request.setOrder(order);
			_package.setRequest(request);
			_package.setHeader(header);
			root.set_package(_package);
			return sendRequest(root);
		}*/
		return null;
	}
	
	/**
	 * 核保回调！
	 * 如果自动核保成功，不需要回调215接口
	 * 如果自动核保失败，保险公司就会通过人工核保，人工核保之后保险公司就会调用215接口通知第三方
	 * @param rootElementGPIC
	 */
	public void doCallBack215(RootElementGPIC rootElementGPIC){
		/*String sessionId = rootElementGPIC.get_package().getHeader().getSessionId();
		String payExpired = rootElementGPIC.get_package().getResponse().getOrder().getPayOutTime();
		String payUrl = rootElementGPIC.get_package().getResponse().getOrder().getPaymentUrl();
		PorderDTO porder = new PorderDTO();
		porder.setSeqNo(sessionId);
		String status = rootElementGPIC.get_package().getHeader().getStatus();
		if(STATUS_101.equals(status)||STATUS_100.equals(status)){
			porder.setVerifyStatus("E");
			porder.setPayUrl(payUrl);
			if(StringUtils.isNotBlank(payExpired)){
				Date date = DateUtils.parseDate(payExpired,new String[]{"yyyy-MM-dd HH:mm:ss"});
				porder.setPayExpired(MyDateUtils.convertToXMLGregorianCalendar(date));
			}
		}else if(STATUS_300.equals(rootElementGPIC.get_package().getHeader().getStatus())){
			porder.setVerifyStatus("F");
		}else{
			porder.setVerifyStatus("O");
		}
		orderClient.updatePorder(porder);*/
	}

	/**
	 * 承保回调！
	 * 支付之后，不管成功与否，保险公司都会回调第三方提供的承保接口230，告知第三方承保结果
	 * @param rootElementGPIC
	 */
	public void doCallBack230(RootElementGPIC rootElementGPIC) {
		/*String sessionId = rootElementGPIC.get_package().getHeader().getSessionId();
		PorderDTO porder = new PorderDTO();
		porder.setSeqNo(sessionId);
		if(STATUS_100.equals(rootElementGPIC.get_package().getHeader().getStatus())){
			boolean result = false;
			porder.setPayStatus("E");
			List<ResponseElementGPIC.Order.SubOrderList.SubOrder> orderList = rootElementGPIC.get_package().getResponse().getOrder().getSubOrderList().getSubOrder();
			for(ResponseElementGPIC.Order.SubOrderList.SubOrder order:orderList){
				PolicyDTO policy = new PolicyDTO();
				policy.setPolicyAppno(order.getProposalNo());
				policy.setVendorId(vendorId);
				policy.setPolicyNo(order.getPolicyNo());
				UpdatePolicyResponse response = orderClient.updatePolicy(policy); 
				result = response.getReturn().isSuccess();
			}
			if(result){
				orderClient.updatePorder(porder);
			}
		}*/
	}
	
	private RootElementGPIC sendRequest(RootElementGPIC root){
		try {
			return (RootElementGPIC)jaxbUtils.xmlToBean(sendRequest(root,gpicConfig.getServiceUrl()));
		} catch (JAXBException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	private String sendRequestEnd(RootElementGPIC root){
		return sendRequest(root,gpicConfig.getServiceUrl());
	}
	
	private String sendRequest(RootElementGPIC root,String address){
		try {
			Map<String,String> properties = new HashMap<String,String>();
			properties.put(Marshaller.JAXB_ENCODING, "GBK");
			
			RootElementGPIC.Package _package = root.get_package();
			RequestElementGPIC request = _package.getRequest();
			
			String requestContent = jaxbUtils.beanToXml(request,properties);
			requestContent = GpicUtils.filterRequestXml(requestContent);
			String xmlSign = GpicUtils.sign(requestContent.getBytes("GBK"),GpicUtils.getPrivateKey(gpicConfig.getPrivateKey()));
			_package.setSign(xmlSign);
			
			String requestXml = GpicUtils.filterPackageListXml(jaxbUtils.beanToXml(root));
			StringEntity myEntity = new StringEntity(requestXml,"GBK");
			String responseXml=Utils.get(HttpExecutor.class).post(address).reqCharset(GpicServiceImpl.Char_GBK)
				.respCharset(GpicServiceImpl.Char_GBK).addHeader("Content-Type", "text/xml; charset=gbk").setEntity(myEntity).executeAsString();
			System.out.println("request: "+requestXml);
			System.out.println("response: "+responseXml);
			return responseXml;
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return null;
	}

}
